#ifndef __REF_SEQ_H__
#define __REF_SEQ_H__

/**
 * the container to read reference sequences from a fasta file
 * to an array with the character type,
 * multiple sequences will be merged linearly,
 * this container is not used for the efficiency,
 * 'N' or 'n' will be discarded (position information will be stored),
 * */

#include <mian_util.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include "common.h"

using namespace std;

struct RefSeq {
	vector<char> seq;
	uint64 numSeq;
	uint64 numBase;

	RefSeq(const char* fileName) {
		this->load(fileName);
	};

	void release() {
		seq.~vector();
	}


	char getBase(const size_t i) {
		return seq.at(i);
	};

	void getSubString(char* str, const uint64 offset, const uint32 size) {
		assert((offset + size) <= this->numBase);

		for(uint32 i = 0; i < size; i++) {
			str[i] = getBase(offset + i);
		}
	};

	void print() {
		for(size_t i = 0; i < this->numBase; i++) {
			printf("%c", this->getBase(i));
		}
		printf("\n");
		printLine();
		printf("Total number of characters: %lu\n", this->numBase);
		printLine();
	}

	void load(const char* fileName) {
		printf("Load data from the disk ...............\n");
		printf("file: %s\n", fileName);
		ifstream ifs(fileName, ifstream::in);
		string line;
		numSeq = 0;
		numBase = 0;
		uint64 numBaseDiscard = 0;

		while(ifs.good()) {
			getline(ifs, line);
			if(line[0] != '>') {	//skip the sequence name
				for(size_t i = 0; i < line.size(); i++) {
					//only push the character with four bases
					if(isGoodBase(line[i])) {
						this->seq.push_back(line[i]);
						numBase++;

						if(numBase%100000000 == 0) {
							printf("\t%lu bases loaded...\n", numBase);
						}
					} else {
						numBaseDiscard++;
					}
				}
			} else {
				numSeq++;
			}
		}

		ifs.close();

		assert(numBase == seq.size());
		printf("\tnumSequence = %lu\n", numSeq);
		printf("\tnumBase = %lu, numBaseDiscard = %lu\n", numBase, numBaseDiscard);
		printf("\tdone.\n");
	};


	void dumpToDisk(const char* fileName, const unsigned int lineWidth) {
		printTitle(__func__);
		assert(numBase == seq.size());
		printf("output file: %s\n", fileName);
		printf("line width: %d\n", lineWidth);
	
		ofstream ofs(fileName, ofstream::out);	
		const uint64 numLine = ceil(numBase/(double)lineWidth);

		ofs << ">ref1" << endl;
		uint64 count = 0;
		for(uint64 i = 0; i < numLine; i++) {
			const uint64 offset = i*lineWidth;
			const uint32 size = (i == (numLine - 1)) ? (numBase - i*lineWidth) : (lineWidth);

			for(uint32 j = offset; j < offset + size; j++) {
				ofs << seq[j];
				count++;
			}
			ofs << endl;	

			if(i%1000000 == 0) {
				printf("\tline %lu done...\n", i);
			}
		}
		ofs.close();

		printf("\tdump 1 sequence done.\n");
		printf("\tlineWidth = %d, numLine = %lu\n", lineWidth, numLine);
		printf("\tnumBase = %lu, successfully dumped bases: %lu\n", 
			numBase, count);
	}
};


#endif /* __REF_SEQ_H__ */


